package caj.springboot.utils;


import caj.springboot.common.ResultCodeEnum;
import caj.springboot.model.exception.BaseException;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.Map;

import static org.apache.ibatis.type.SimpleTypeRegistry.isSimpleType;

/**
 * @description: http手动封装工具类
 * @author: CAJ
 * @time: 2025/09/06 16:27
 */

@Slf4j
public class HttpUtils {

    //超时时间 3秒（根据需要可以在配置类中配置）
    private final static Integer TIME_OUT = 3000;

    /**
     * post请求
     *
     * @param url  请求地址
     * @param body 请求体
     * @return 响应结果
     */
    public static Object post(String url, String body) {
        log.info("post请求：url:{},参数：{}", url, body);
        String responseResult = HttpUtil.createPost(url)
                .charset(StandardCharsets.UTF_8)
                .timeout(TIME_OUT)
                .body(body)
                .execute()
                .body();
        log.info("响应结果:{}", responseResult);
        return parseResponse(responseResult);
    }

    /**
     * post请求
     *
     * @param url  请求地址
     * @param body 请求体
     * @return 响应结果
     */
    public static <T> T post(String url, String body, Class<T> clazz) {
        log.info("post请求：url:{},参数：{}", url, body);
        String responseResult = HttpUtil.createPost(url)
                .charset(StandardCharsets.UTF_8)
                .timeout(TIME_OUT)
                .body(body)
                .execute()
                .body();
        log.info("响应结果:{}", responseResult);
        return parseResponse(responseResult, clazz);
    }

    /**
     * get 请求
     *
     * @param url 请求地址
     * @return 响应结果
     */
    public static Object get(String url) {
        log.info("get请求：url:{}", url);
        String responseResult = HttpUtil.createGet(url)
                .charset(StandardCharsets.UTF_8)
                .timeout(TIME_OUT)
                .execute()
                .body();
        log.info("响应结果:{}", responseResult);
        return parseResponse(responseResult);
    }

    /**
     * 带参数的get请求
     *
     * @param url 请求地址
     * @param params 传入参数
     * @return 相应结果
     */
    public static Object get(String url, Map<String, Object> params) {
        log.info("GET请求：url:{}, params:{}", url, params);
        String responseResult = HttpUtil.createGet(url)
                .charset(StandardCharsets.UTF_8)
                .timeout(TIME_OUT)
                .form(params)
                .execute()
                .body();
        log.info("响应结果:{}", responseResult);
        return parseResponse(responseResult);
    }

    /**
     * get请求
     *
     * @param url 请求地址
     * @param clazz 数据类型
     * @return 对应数据类型的数据
     * @param <T>
     */
    public static <T> T get(String url , Class<T> clazz) {
        log.info("get请求：url:{}", url);
        String responseResult = HttpUtil.createGet(url)
                .charset(StandardCharsets.UTF_8)
                .timeout(TIME_OUT)
                .execute()
                .body();
        log.info("响应结果:{}", responseResult);
        return parseResponse(responseResult, clazz);
    }

    /**
     * 带参数的get请求
     *
     * @param url 请求地址
     * @param params 传入参数
     * @return 相应结果
     */
    public static <T> T get(String url, Map<String, Object> params, Class<T> clazz) {
        log.info("GET请求：url:{}, params:{}", url, params);
        String responseResult = HttpUtil.createGet(url)
                .charset(StandardCharsets.UTF_8)
                .timeout(TIME_OUT)
                .form(params)
                .execute()
                .body();
        log.info("响应结果:{}", responseResult);
        return parseResponse(responseResult, clazz);
    }

    /**
     * get 请求
     *
     * @param url 请求地址
     * @return 响应结果
     */
    public static JSONObject getObj(String url) {
        log.info("getObj请求：url:{}", url);
        String responseResult = HttpUtil.createGet(url)
                .charset(StandardCharsets.UTF_8)
                .timeout(TIME_OUT)
                .execute()
                .body();
        log.info("响应结果:{}", responseResult);
        return (JSONObject) parseResponse(responseResult);
    }

    /**
     * get 请求
     *
     * @param url 请求地址
     * @param params 传入参数
     * @return 响应结果
     */
    public static JSONObject getObj(String url, Map<String, Object> params) {
        log.info("getObj请求：url:{}", url);
        String responseResult = HttpUtil.createGet(url)
                .charset(StandardCharsets.UTF_8)
                .timeout(TIME_OUT)
                .form(params)
                .execute()
                .body();
        log.info("响应结果:{}", responseResult);
        return (JSONObject) parseResponse(responseResult);
    }

    /**
     * get 请求
     *
     * @param url 请求地址
     * @return 响应结果
     */
    public static JSONArray getArr(String url) {
        log.info("getArr请求：url:{}", url);
        String responseResult = HttpUtil.createGet(url)
                .charset(StandardCharsets.UTF_8)
                .timeout(TIME_OUT)
                .execute()
                .body();
        log.info("响应结果:{}", responseResult);
        return (JSONArray) parseResponse(responseResult);
    }

    /**
     * get 请求
     *
     * @param url 请求地址
     * @param params 传入参数
     * @return 响应结果
     */
    public static JSONArray getArr(String url, Map<String, Object> params) {
        log.info("getArr请求：url:{}", url);
        String responseResult = HttpUtil.createGet(url)
                .charset(StandardCharsets.UTF_8)
                .timeout(TIME_OUT)
                .form(params)
                .execute()
                .body();
        log.info("响应结果:{}", responseResult);
        return (JSONArray) parseResponse(responseResult);
    }

    /**
     * 解析响应数据
     *
     * @param responseStr 响应字符串
     * @return Object
     */
    public static Object parseResponse(String responseStr) {
        if (StrUtil.isBlank(responseStr)) {
            throw new BaseException("服务未响应信息");
        }
        boolean jsonObj = JSONUtil.isTypeJSONObject(responseStr);
        if (!jsonObj) {
            log.error("服务响应格式错误,不是JSON格式");
            throw new BaseException("服务响应格式错误");
        }

        JSONObject responseJson = JSON.parseObject(responseStr);
        Integer code = responseJson.getInteger("code");
        // 这个需要解析外界的code，可能需要调整
        if (code == null || (code != 200 && code != ResultCodeEnum.SUCCESS.getCode())) {
            String msg;
            if (StrUtil.isNotBlank(responseJson.getString("msg"))) {
                msg = responseJson.getString("msg");
            } else if (StrUtil.isNotBlank(responseJson.getString("message"))) {
                msg = responseJson.getString("message");
            } else {
                msg = "服务异常";
            }
            throw new BaseException("服务访问出错:" + msg);
        }
        return responseJson.get("data");
    }

    /**
     * 解析响应并返回指定类型
     * @param responseStr 响应字符串
     * @param clazz 返回数据类型class
     * @return Object
     */
    public static <T> T parseResponse(String responseStr, Class<T> clazz) {
        if (StrUtil.isBlank(responseStr)) {
            throw new BaseException("服务未响应信息");
        }

        if (!JSONUtil.isTypeJSONObject(responseStr)) {
            log.error("服务响应格式错误,不是JSON格式");
            throw new BaseException("服务响应格式错误");
        }

        JSONObject responseJson = JSON.parseObject(responseStr);
        Integer code = responseJson.getInteger("code");

        if (code == null || (code != 200 && code != ResultCodeEnum.SUCCESS.getCode())) {
            String msg;
            if (StrUtil.isNotBlank(responseJson.getString("msg"))) {
                msg = responseJson.getString("msg");
            } else if (StrUtil.isNotBlank(responseJson.getString("message"))) {
                msg = responseJson.getString("message");
            } else {
                msg = "服务异常";
            }
            throw new BaseException("服务访问出错:" + msg);
        }

        Object data = responseJson.get("data");
        if (data == null) {
            return null;
        }

        // 处理数字类型转换
        if (data instanceof Number) {
            return convertNumber((Number) data, clazz);
        }
        // 因为responseJson.getObject("data", clazz)只能转一个内容为简单数据类型的对象
        // 而JSONUtil.toBean(JSONUtil.toJsonStr(data), clazz)多了一个序列化和反序列化的过程，通用性比较高
        return JSONUtil.toBean(JSONUtil.toJsonStr(data), clazz);
    }

    /**
     * 处理数字类型的数据，因为如果类型数数字类型，结果会默认生成Integer类型
     * @param number
     * @param clazz
     * @return
     * @param <T>
     */
    private static <T> T convertNumber(Number number, Class<T> clazz) {
        if (clazz == Long.class) {
            return clazz.cast(number.longValue());
        } else if (clazz == Integer.class) {
            return clazz.cast(number.intValue());
        } else if (clazz == Double.class) {
            return clazz.cast(number.doubleValue());
        } else if (clazz == Float.class) {
            return clazz.cast(number.floatValue());
        } else if (clazz == Short.class) {
            return clazz.cast(number.shortValue());
        } else if (clazz == Byte.class) {
            return clazz.cast(number.byteValue());
        } else if (clazz == BigDecimal.class) {
            return clazz.cast(BigDecimal.valueOf(number.doubleValue()));
        }
        // 如果是不支持的Number类型，让FastJSON处理
        throw new BaseException("不支持的数值类型转换: " + clazz.getSimpleName());
    }

    /**
     * 获取请求超时时间
     *
     * @return 超时时间
     */
    public static Integer getRequestTimeOut() {
        return HttpUtils.TIME_OUT;
    }


}
